#include "../include/fsext.h"
#include "../include/buffer.h"
#include "../include/inode.h"
#include "../include/macro_extent.h"

void FsExt::handle3(ParaForShare* para) const
{
	const Inode* inode=para->pinode;
	para->block_num=reinterpret_cast<uint32>(inode->blockPtrs());
	para->is_indblock=false;
	handleInAddrBlock(para);
	para->is_indblock=true;
	para->block_num=*((uint32*)(inode->blockPtrs()) + 12);
	para->level=1;
	handleInIndblocks(para);
	para->block_num=*((uint32*)(inode->blockPtrs()) + 13);
	para->level=2;
	handleInIndblocks(para);
	para->block_num=*((uint32*)(inode->blockPtrs()) + 14);
	para->level=3;
	handleInIndblocks(para);
}
void FsExt::handleInIndblocks(ParaForShare* para) const
{
	if(!isBlockValid(para->block_num))
		return;
	static uint32 re_times=0;
	re_times++;
	if(re_times==para->level)
		handleInAddrBlock(para);
	else
	{
		Buffer buffer(block_size);
		readBlocks(para->block_num,buffer,1);
		for(uint32 i=0;i<block_size;i+=4)
		{
			para->block_num=*(uint32*)(buffer.data()+i);
			handleInIndblocks(para);
		}
	}
	re_times--;
}
void FsExt::handleInAddrBlock(ParaForShare* para) const
{
	std::vector<const uint32*> block_nums;
	Buffer buffer(block_size);
	if(!para->is_indblock)
		groupBlockNum(reinterpret_cast<const uint32*>(para->block_num),block_nums,12);
	else
	{
		if(!isBlockValid(para->block_num))
			return;
		readBlocks(para->block_num,buffer,1);
		groupBlockNum((uint32*)buffer.data(),block_nums,block_size>>2);
	}
	for(uint32 i=0;i<block_nums.size()-1;i++)
	{
		para->block_num=*block_nums[i];
		para->block_count=block_nums[i+1]-block_nums[i];
		(this->*(para->handle_way))(para);
	}
}

void FsExt::handle4(ParaForShare* para) const
{
	const Inode* inode=para->pinode;
	for(uint32 i=EXTENT_SIZE;i<=EXTENT_COUNT(inode->extentPtr())*EXTENT_SIZE;i+=EXTENT_SIZE)
	{
		if(DEPTH_OF_TREE(inode->extentPtr())!=0)
		{
			para->block_num=BLOCK_NUM_IN_EXTENT_IDX(inode->extentPtr()+i);
			handleInExtentIdx(para);
		}
		else
		{
			para->block_num=BLOCK_NUM_IN_EXTENT(inode->extentPtr()+i);
			para->block_count=(uint32)BLOCK_COUNT_IN_EXTENT(inode->extentPtr()+i);
			(this->*(para->handle_way))(para);
		}
	}
}
void FsExt::handleInExtentIdx(ParaForShare* para) const
{
	if(!isBlockValid(para->block_num))
		return;
	Buffer buffer(block_size);
	readBlocks(para->block_num,buffer,1);
	for(uint32 i=EXTENT_SIZE;i<=EXTENT_COUNT(buffer.data())*EXTENT_SIZE;i+=EXTENT_SIZE)
	{
		if(DEPTH_OF_TREE(buffer.data())!=0)
		{
			para->block_num=BLOCK_NUM_IN_EXTENT_IDX(buffer.data()+i);
			handleInExtentIdx(para);
		}
		else
		{
			para->block_num=BLOCK_NUM_IN_EXTENT(buffer.data()+i);
			para->block_count=(uint32)BLOCK_COUNT_IN_EXTENT(buffer.data()+i);
			(this->*(para->handle_way))(para);
		}
	}
}


